#include "llt.h"

#include <stdio.h>

#include <hal_mtd.h>
#include <k_tick.h>

#define BLOCK_START_ADDR  0                                  /* Block start address      */
#define NUM_OF_BLOCKS     20                                 /* Total number of blocks   */
#define BUFFER_WORDS_SIZE ((BLOCKSIZE * NUM_OF_BLOCKS) >> 2) /* Total data size in bytes */

static uint32_t tx_buf[BUFFER_WORDS_SIZE];
static uint32_t rx_buf[BUFFER_WORDS_SIZE];

static void __fill_buffer(uint32_t *pBuffer, uint32_t uwBufferLenght, uint32_t uwOffset)
{
    uint32_t tmpIndex = 0;

    /* Put in global buffer different values */
    for (tmpIndex = 0; tmpIndex < uwBufferLenght; tmpIndex++) {
        pBuffer[tmpIndex] = tmpIndex + uwOffset;
    }
}

static uint8_t __cmp_buffer(uint32_t *pBuffer1, uint32_t *pBuffer2, uint16_t BufferLength)
{
    while (BufferLength--) {
        if (*pBuffer1 != *pBuffer2) {
            return 1;
        }
        pBuffer1++;
        pBuffer2++;
    }
    return 0;
}

static void test_emmc_demo(void **state)
{
    int ret;

    hal_mtd_t *mtd = hal_mtd_open("emmc1");
    assert_true(mtd != NULL);

    ret = hal_mtd_erase_block(mtd, BLOCK_START_ADDR, NUM_OF_BLOCKS);
    assert_int_equal(ret, 0);

    __fill_buffer(tx_buf, BUFFER_WORDS_SIZE, 0x22FF);

    uint32_t start = tick_ms();
    ret = hal_mtd_write_block(mtd, BLOCK_START_ADDR, NUM_OF_BLOCKS, (uint8_t *)tx_buf);
    uint32_t end = tick_ms();
    if (start != end) {
        printf("start: %lu ms, end: %lu ms, write speed: %lu\n", start, end,
               (NUM_OF_BLOCKS * 512) * 1000 / (end - start));
    }
    assert_int_equal(ret, 0);

    ret = hal_mtd_read_block(mtd, BLOCK_START_ADDR, NUM_OF_BLOCKS, (uint8_t *)rx_buf);
    assert_int_equal(ret, 0);

    ret = __cmp_buffer((uint32_t *)tx_buf, (uint32_t *)rx_buf, NUM_OF_BLOCKS);
    assert_int_equal(ret, 0);
}

/** test entry */

void test_emmc(struct tester_case *caser)
{
    UnitTest tests[] = {
        unit_test(test_emmc_demo),
    };

    caser->stats->totals = sizeof(tests) / sizeof(tests[0]);
    caser->stats->fails = run_tests(tests);
}

TESTER_CASE_DEF("test_emmc", test_emmc, NULL, NULL, 0);
